import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
import os

class EnhancedImageSelector(tk.Frame):
    def __init__(self, parent, label_text="选择图片:", default_path="", preview_size=(200, 150)):
        super().__init__(parent)
        self.preview_size = preview_size
        self.current_image_path = ""
        self.photo_image = None
        self.drag_data = {"x": 0, "y": 0}
        
        self.pack(pady=5, padx=20, fill=tk.X)
        self.setup_ui(label_text, default_path)
        self.setup_drag_drop()
    
    def setup_ui(self, label_text, default_path):
        """设置用户界面"""
        # 标签
        self.label = tk.Label(self, text=label_text, font=("Arial", 12, "bold"))
        self.label.pack(anchor="w")
        
        # 主要内容框架
        content_frame = tk.Frame(self)
        content_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 左侧：输入和按钮
        left_frame = tk.Frame(content_frame)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
        
        # 文件路径输入框
        self.path_entry = tk.Entry(left_frame, font=("Arial", 10))
        self.path_entry.pack(fill=tk.X, pady=(0, 5))
        self.path_entry.bind('<KeyRelease>', self.on_path_change)
        
        # 按钮框架
        button_frame = tk.Frame(left_frame)
        button_frame.pack(fill=tk.X)
        
        # 选择文件按钮
        self.browse_button = tk.Button(
            button_frame, 
            text="浏览文件", 
            command=self.browse_file,
            bg="lightblue"
        )
        self.browse_button.pack(side=tk.LEFT, padx=(0, 5))
        
        # 清除按钮
        self.clear_button = tk.Button(
            button_frame,
            text="清除",
            command=self.clear_image,
            bg="lightcoral"
        )
        self.clear_button.pack(side=tk.LEFT, padx=(0, 5))
        
        # 复制路径按钮
        self.copy_button = tk.Button(
            button_frame,
            text="复制路径",
            command=self.copy_path,
            bg="lightgreen"
        )
        self.copy_button.pack(side=tk.LEFT)

        # 右侧：预览区域
        preview_frame = tk.Frame(content_frame, relief=tk.SUNKEN, bd=2)
        preview_frame.pack(side=tk.RIGHT)
        
        # 预览标签
        self.preview_label = tk.Label(
            preview_frame,
            text="拖拽图片到这里\n或点击浏览文件",
            width=25,
            height=10,
            bg="white",
            relief=tk.FLAT,
            cursor="hand2"
        )
        self.preview_label.pack(padx=5, pady=5)
        self.preview_label.bind("<Button-1>", lambda e: self.browse_file())
        
        # 状态信息
        self.info_label = tk.Label(self, text="", font=("Arial", 8), fg="gray")
        self.info_label.pack(anchor="w", pady=(5, 0))
        
        # 设置默认路径
        if default_path and os.path.exists(default_path):
            self.set_image_path(default_path)
        else:
            self.show_placeholder()
    
    def setup_drag_drop(self):
        """设置拖拽功能"""
        # 绑定拖拽事件（Windows）
        try:
            import tkinterdnd2 as tkdnd
            
            # 启用拖拽
            self.preview_label.drop_target_register(tkdnd.DND_FILES)
            self.preview_label.dnd_bind('<<Drop>>', self.on_drop)
            self.preview_label.dnd_bind('<<DragEnter>>', self.on_drag_enter)
            self.preview_label.dnd_bind('<<DragLeave>>', self.on_drag_leave)
            
        except ImportError:
            # 如果没有安装 tkinterdnd2，使用基础的鼠标事件
            self.preview_label.bind("<Button-1>", lambda e: self.browse_file())
    
    def on_drop(self, event):
        """处理文件拖拽放下事件"""
        files = event.data.split()
        if files:
            file_path = files[0].strip('{}')  # 移除可能的大括号
            if self.is_image_file(file_path):
                self.set_image_path(file_path)
            else:
                messagebox.showerror("错误", "请拖拽图片文件")
    
    def on_drag_enter(self, event):
        """拖拽进入时的视觉反馈"""
        self.preview_label.config(bg="lightblue")
    
    def on_drag_leave(self, event):
        """拖拽离开时恢复样式"""
        self.preview_label.config(bg="white")
    
    def browse_file(self):
        """打开文件选择对话框"""
        filetypes = [
            ("图片文件", "*.jpg *.jpeg *.png *.bmp *.gif *.tiff *.webp"),
            ("JPEG文件", "*.jpg *.jpeg"),
            ("PNG文件", "*.png"),
            ("BMP文件", "*.bmp"),
            ("所有文件", "*.*")
        ]
        
        initial_dir = os.path.dirname(self.current_image_path) if self.current_image_path else os.getcwd()
        
        filename = filedialog.askopenfilename(
            title="选择图片文件",
            filetypes=filetypes,
            initialdir=initial_dir
        )
        
        if filename:
            self.set_image_path(filename)
    
    def clear_image(self):
        """清除选择的图片"""
        self.current_image_path = ""
        self.path_entry.delete(0, tk.END)
        self.show_placeholder()
    
    def copy_path(self):
        """复制路径到剪贴板"""
        if self.current_image_path:
            self.clipboard_clear()
            self.clipboard_append(self.current_image_path)
            messagebox.showinfo("成功", "路径已复制到剪贴板")
        else:
            messagebox.showwarning("提示", "没有选择图片")
    
    def on_path_change(self, event=None):
        """路径输入框内容改变时的回调"""
        path = self.path_entry.get().strip()
        if path != self.current_image_path:
            self.set_image_path(path)
    
    def set_image_path(self, path):
        """设置图片路径并更新预览"""
        self.current_image_path = path
        self.path_entry.delete(0, tk.END)
        self.path_entry.insert(0, path)
        self.update_preview()
    
    def update_preview(self):
        """更新图片预览"""
        if not self.current_image_path:
            self.show_placeholder()
            return
        
        if not os.path.exists(self.current_image_path):
            self.show_error("文件不存在")
            return
        
        try:
            with Image.open(self.current_image_path) as img:
                # 获取原始尺寸
                original_size = img.size
                
                # 计算缩放比例，保持宽高比
                preview_w, preview_h = self.preview_size
                scale = min(preview_w / original_size[0], preview_h / original_size[1])
                new_size = (int(original_size[0] * scale), int(original_size[1] * scale))
                
                # 调整大小
                img_resized = img.resize(new_size, Image.Resampling.LANCZOS)
                
                # 转换为 Tkinter 可用的格式
                self.photo_image = ImageTk.PhotoImage(img_resized)
                
                # 更新预览标签
                self.preview_label.config(
                    image=self.photo_image,
                    text="",
                    bg="white",
                    width=preview_w,
                    height=preview_h
                )
                
                # 更新状态信息
                file_size = os.path.getsize(self.current_image_path)
                if file_size < 1024:
                    size_str = f"{file_size} B"
                elif file_size < 1024 * 1024:
                    size_str = f"{file_size / 1024:.1f} KB"
                else:
                    size_str = f"{file_size / (1024 * 1024):.2f} MB"
                
                filename = os.path.basename(self.current_image_path)
                self.info_label.config(
                    text=f"📁 {filename} | 🖼️ {original_size[0]}×{original_size[1]} | 📦 {size_str}",
                    fg="green"
                )
                
        except Exception as e:
            self.show_error(f"无法加载图片: {str(e)}")
    
    def show_placeholder(self):
        """显示占位符"""
        self.photo_image = None
        self.preview_label.config(
            image="",
            text="📷\n\n拖拽图片到这里\n或点击浏览文件\n\n支持格式: JPG, PNG, BMP, GIF",
            bg="lightgray",
            width=25,
            height=10
        )
        self.info_label.config(text="尚未选择图片", fg="gray")
    
    def show_error(self, error_msg):
        """显示错误信息"""
        self.photo_image = None
        self.preview_label.config(
            image="",
            text=f"❌\n\n{error_msg}",
            bg="lightcoral",
            width=25,
            height=10
        )
        self.info_label.config(text=error_msg, fg="red")
    
    def get_image_path(self):
        """获取当前选择的图片路径"""
        return self.current_image_path
    
    def is_valid(self):
        """检查当前选择的图片是否有效"""
        return (self.current_image_path and 
                os.path.exists(self.current_image_path) and 
                self.is_image_file(self.current_image_path))
    
    def is_image_file(self, path):
        """检查文件是否为图片格式"""
        valid_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff', '.webp'}
        return os.path.splitext(path.lower())[1] in valid_extensions

# 使用示例
if __name__ == "__main__":
    root = tk.Tk()
    root.title("图片选择器测试")
    root.geometry("800x600")
    
    # 创建两个图片选择器
    selector1 = EnhancedImageSelector(root, "钓鱼按钮图片:", "fish.png")
    selector2 = EnhancedImageSelector(root, "鱼鳔图片:", "fishing.png")
    
    # 测试按钮
    def test_get_paths():
        print(f"图片1: {selector1.get_image_path()}")
        print(f"图片2: {selector2.get_image_path()}")
        print(f"图片1有效: {selector1.is_valid()}")
        print(f"图片2有效: {selector2.is_valid()}")
    
    test_button = tk.Button(root, text="获取路径", command=test_get_paths)
    test_button.pack(pady=20)
    
    root.mainloop()